유사도 (Similarity)란

유사도(Similarity)는 두 데이터 객체가 얼마나 서로 비슷한지를 나타내는 척도입니다.
0과 1 사이의 값으로 표현되며, 값이 1에 가까울수록 두 데이터가 매우 비슷하다는 의미입니다.
유사도는 추천 시스템, 텍스트 마이닝, 이미지 검색 등 다양한 분야에서 사용됩니다.

대표적인 유사도 측정 방법

1. 코사인 유사도 (Cosine Similarity)

코사인 유사도는 두 벡터 사이의 방향이 얼마나 비슷한지를 측정합니다.
벡터의 크기보다는 방향에 초점을 맞추기 때문에, 주로 문서나 텍스트 데이터의 유사도를 계산하는 데 널리 사용됩니다.

핵심 개념

  • 두 벡터가 이루는 각도의 코사인 값.
  • 두 벡터의 방향이 완전히 같으면 1, 90°의 각을 이루면 0, 완전히 반대 방향이면 -1의 값을 가집니다.

계산

두 벡터의 내적을 각각의 크기(노름)의 곱으로 나눕니다.

$$ \text{Cosine Similarity} = \frac{A \cdot B}{\|A\| \|B\|} $$

예시

"나는 사과가 좋다"와 "나는 사과가 정말 좋다"라는 두 문장은 단어의 개수(벡터의 크기)는 다르지만,
'사과'와 '좋다'는 방향성이 같으므로 코사인 유사도가 높게 나옵니다.

2. 자카드 유사도 (Jaccard Similarity)

자카드 유사도는 두 집합이 얼마나 많은 요소를 공유하는지를 측정합니다.
주로 집합 데이터 간의 유사성을 비교하는 데 사용되며, 결과는 0과 1 사이의 값을 가집니다.

핵심 개념

두 집합의 교집합(공통된 원소)의 크기를 합집합(전체 원소)의 크기로 나눈 값입니다.

$$ \text{Jaccard Similarity} = \frac{|A \cap B|}{|A \cup B|} $$

예시

  • A의 장바구니: {사과, 바나나, 우유}
  • B의 장바구니: {사과, 빵, 우유}
  • 교집합(공통 상품): {사과, 우유} (2개)
  • 합집합(전체 상품): {사과, 바나나, 우유, 빵} (4개)
  • 자카드 유사도 = 2 / 4 = 0.5

3. 유클리드 거리 (Euclidean Distance)와 유사도

유클리드 거리는 두 점 사이의 직선 거리를 측정하는 가장 일반적인 방법입니다.
거리가 가까울수록 두 데이터가 비슷하다고 판단할 수 있으므로, 유사도를 계산하는 데 활용될 수 있습니다.

핵심 개념

  • 좌표 공간상에서 두 점을 잇는 가장 짧은 거리.
  • 각 차원별 차이의 제곱을 모두 더한 후 제곱근을 씌웁니다.

계산

$$ d = \sqrt{\sum_{i=1}^{n} (q_i - p_i)^2} $$

유사도로의 변환 및 예시

  • 유클리드 거리는 값이 작을수록 유사하므로, 보통 `1 / (1 + 거리)` 와 같은 방식으로 변환하여 0과 1 사이의 유사도 값으로 사용합니다. 거리가 0이면 유사도는 1이 됩니다.
  • 사용자의 평점 데이터를 좌표평면의 점으로 보고, 두 사용자 간의 거리를 계산하여 취향이 비슷한 사용자를 찾는 데 사용할 수 있습니다.

문장 유사도 분석: 실제 계산 예시

1단계
문장을 벡터로 변환 (Bag-of-Words)

먼저 각 문장에 특정 단어가 몇 번 나타나는지를 세어 숫자 벡터로 만듭니다. 여기서 단어 주머니(Vocabulary)는 {love, apple, delicious, ...} 라고 가정합니다.

문장 내용 벡터 (Vector) 크기 (Magnitude)
1 I love apple. [1, 1, 0, ...] $$ \sqrt{1^2 + 1^2} = \sqrt{2} $$
2 Apple is delicious which I love too. [1, 1, 1, ...] $$ \sqrt{1^2 + 1^2 + 1^2} = \sqrt{3} $$
3 I want a delicious food, but not an apple. [0, 1, 1, ...] $$ \sqrt{0^2 + 1^2 + 1^2} = \sqrt{2} $$
4 Deep learning is difficult. [0, 0, 0, ...] $$ \sqrt{0} = 0 $$

2단계
코사인 유사도 계산

벡터화된 문장들을 바탕으로 코사인 유사도 공식을 적용하여 실제 유사도 점수를 계산합니다.

[1, 2]: 1번 문장 vs 2번 문장

  • 분자 (내적)
    (1 * 1) + (1 * 1) + (0 * 1) = 2
  • 분모 (크기의 곱)
    $$ \sqrt{2} \times \sqrt{3} = \sqrt{6} $$
$$ \cos(\theta) = \frac{2}{\sqrt{6}} \approx 0.816 $$

➡️ 결론 점수가 1에 가까워 매우 유사하다고 판단합니다.

[2, 4]: 2번 문장 vs 4번 문장

  • 분자 (내적)
    (1 * 0) + (1 * 0) + (1 * 0) = 0
  • 분모 (크기의 곱)
    $$ \sqrt{3} \times 0 = 0 $$
$$ \cos(\theta) = \frac{0}{\sqrt{3}} = 0 $$

➡️ 결론 점수가 0이므로 전혀 유사하지 않다고 판단합니다.

[1, 3]: 1번 문장 vs 3번 문장

  • 분자 (내적)
    (1 * 0) + (1 * 1) + (0 * 1) = 1
  • 분모 (크기의 곱)
    $$ \sqrt{2} \times \sqrt{2} = 2 $$
$$ \cos(\theta) = \frac{1}{2} = 0.5 $$

➡️ 결론 'apple' 단어만 겹쳐 0.5의 유사도를 가집니다. 어느 정도 관련은 있지만, [1, 2] 경우보다는 유사도가 낮다고 해석할 수 있습니다.


또 다른 거리 척도
레벤슈타인 거리

4. 레벤슈타인 거리 (Levenshtein Distance)

레벤슈타인 거리는 두 문자열(단어 또는 문장)이 얼마나 다른지를 측정하는 '편집 거리(Edit Distance)'의 한 종류입니다.
이 값은 유사도가 아니라 '거리'이므로, 값이 작을수록 두 문자열이 더 비슷하다는 의미입니다.

핵심 개념

  • 문자열 A를 문자열 B로 바꾸기 위해 필요한 최소한의 편집 횟수를 계산합니다.
  • 세 가지 연산
    • 삽입 (Insertion)
      문자를 추가하는 연산
    • 삭제 (Deletion)
      문자를 제거하는 연산
    • 변경 (Substitution)
      한 문자를 다른 문자로 바꾸는 연산

"가나다"와 "가다라" 사이의 거리 계산 예시

  1. "가다"에서 '나'를 '다'로 변경합니다. → "가다" (비용: 1)
  2. "가다"에서 마지막 '다'를 '라'로 변경합니다. → "가다" (비용: 1)

➡️ 결론 총 2번의 '변경' 연산이 필요했으므로, "가나다"와 "가다라"의 레벤슈타인 거리는 2입니다.

어디에 사용될까요?

  • 철자 교정기
    'aple'을 입력했을 때 거리가 1인 'apple'을 추천합니다.
  • 검색 엔진
    오타를 입력해도 "이것을 찾으셨나요?"라며 비슷한 단어를 제안합니다.
  • DNA 염기서열 분석
    두 DNA 시퀀스가 얼마나 유사한지 비교하는 데 사용됩니다.

출처 및 참고 자료

메타코드M : 딥러닝 자연어처리 유사도 분석을 18분만에 정리해드립니다